package cc.shacocloud.mirage.loader.jar;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Permission;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;

/**
 * 用于创建 {@link JarFile} 副本的包装器，以便可以安全地关闭它，而无需关闭原始文件
 *
 * @author Phillip Webb
 */
class JarFileWrapper extends AbstractJarFile {
    
    private final JarFile parent;
    
    JarFileWrapper(@NotNull JarFile parent) throws IOException {
        super(parent.getRootJarFile().getFile());
        this.parent = parent;
        if (System.getSecurityManager() == null) {
            super.close();
        }
    }
    
    @Contract("null -> fail")
    static @NotNull JarFile unwrap(java.util.jar.JarFile jarFile) {
        if (jarFile instanceof JarFile) {
            return (JarFile) jarFile;
        }
        if (jarFile instanceof JarFileWrapper) {
            return unwrap(((JarFileWrapper) jarFile).parent);
        }
        throw new IllegalStateException("不是 JarFile 或 JarFileWrapper");
    }
    
    @Override
    URL getUrl() throws MalformedURLException {
        return this.parent.getUrl();
    }
    
    @Override
    JarFileType getType() {
        return this.parent.getType();
    }
    
    @Override
    Permission getPermission() {
        return this.parent.getPermission();
    }
    
    @Override
    public Manifest getManifest() throws IOException {
        return this.parent.getManifest();
    }
    
    @Override
    public Enumeration<JarEntry> entries() {
        return this.parent.entries();
    }
    
    @Override
    public Stream<JarEntry> stream() {
        return this.parent.stream();
    }
    
    @Override
    public JarEntry getJarEntry(String name) {
        return this.parent.getJarEntry(name);
    }
    
    @Override
    public ZipEntry getEntry(String name) {
        return this.parent.getEntry(name);
    }
    
    @Override
    InputStream getInputStream() throws IOException {
        return this.parent.getInputStream();
    }
    
    @Override
    public synchronized InputStream getInputStream(ZipEntry ze) throws IOException {
        return this.parent.getInputStream(ze);
    }
    
    @Override
    public String getComment() {
        return this.parent.getComment();
    }
    
    @Override
    public int size() {
        return this.parent.size();
    }
    
    @Override
    public String toString() {
        return this.parent.toString();
    }
    
    @Override
    public String getName() {
        return this.parent.getName();
    }
    
}
